グリッドサーチ(grid search)
Overview
グリッドサーチは、パラメータのすべての組み合わせに対して試してみる方法です。
Coding
単純なグリッドサーチ
カーネル法を用いたSVCを例に見てみます。SVCの重要なパラメータは、Cとgammaがありました。単純なグリッドサーチでは、ただのforループで実装できます。
code: Python
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=0)
print('Size of training set: {} size of test set: {}'.format(X_train.shape0, X_test.shape0)) best_score = 0
# それぞれのパラメータの組み合わせに対してSVCを訓練
svm = SVC(gamma=gamma, C=C)
svm.fit(X_train, y_train)
# SVCをテストセットで評価
score = svm.score(X_test, y_test)
# 良いスコアだったらスコアとパラメータを保存
if score > best_score:
best_score = score
best_parameters = {'C': C, 'gamma': gamma}
print("Best score: {:.2f}".format(best_score))
print("Best parameters: {}".format(best_parameters))
--------------------------------------------------------------------------
Size of training set: 112 size of test set: 38
Best score: 0.97
Best parameters: {'C': 100, 'gamma': 0.001}
--------------------------------------------------------------------------
パラメータの過剰適合の危険性と検証セット
上の結果をみて高い精度がでたと思うのは間違いです。なぜなら、この場合のテストデータセットだけに対して精度が高くなるようにパラメータを組み合わせただけに過ぎないからです。この問題を解決するためには、データをもう一度分割し、3つのセットにします。下図のように、訓練セット、検証セット(パラメータ選択用)、テストセット(評価用)に分割します。
https://gyazo.com/d37760010154d077e8ed6110603c1e7c
訓練セットで学習し、検証セットを用いて最良のパラメータを選択したら、そのパラメータを用いてモデルを再構築します。この際、学習には、訓練データだけでなく検証データも使います。こうすると、可能な限りデータを有効に利用してモデルを構築することができます。
code: Python
from sklearn.svm import SVC
# データを訓練+検証セットとテストセットに分割する
X_trainval, X_test, y_trainval, y_test = train_test_split(iris.data, iris.target, random_state=0)
# 訓練+検証セットを訓練セットと検証セットに分割する
X_train, X_valid, y_train, y_valid = train_test_split(X_trainval, y_trainval, random_state=1)
print('Size of training set: {} size of validation set: {} size of test set:'
' {}\n'.format(X_train.shape0, X_valid.shape0, X_test.shape0)) best_score = 0
# それぞれのパラメータの組み合わせに対してSVCを訓練
svm = SVC(gamma=gamma, C=C)
svm.fit(X_train, y_train)
# SVCを検証セットで評価
score = svm.score(X_valid, y_valid)
# 良いスコアだったらスコアとパラメータを保存
if score > best_score:
best_score = score
best_parameters = {'C': C, 'gamma': gamma}
# 訓練セットと検証セットを用いてモデルを再構築し、テストセットで評価
svm = SVC(**best_parameters)
svm.fit(X_trainval, y_trainval)
test_score = svm.score(X_test, y_test)
# 検証セットに対する最良のスコア
print('Best score on validation set: {:.2f}'.format(best_score))
# 最良のパラメータ
print('Best parameters: ', best_parameters)
# 最良のパラメータを用いたテストセットに対するスコア
print('Test set score with best parameters: {:.2f}'.format(test_score))
--------------------------------------------------------------------------
Size of training set: 84 size of validation set: 28 size of test set: 38
Best score on validation set: 0.96
Best parameters: {'C': 10, 'gamma': 0.001}
Test set score with best parameters: 0.92
--------------------------------------------------------------------------
交差検証を用いたグリッドサーチ
汎化性能をより良く見積もるためには、訓練セットと検証セットの分割を一度行うのではなく、それぞれのパラメータの組み合わせに対して交差検証を行うと良いです。また、多くの人が、交差検証を用いたグリッドサーチを指して交差検証(cross-validation)という言葉を使っています。scikit-learnでは、こうした交差検証を用いたグリッドサーチを実装したGridSearchCVクラスを提供しています。
code: Python
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
param_grid = {'C': 0.001, 0.01, 0.1, 1, 10, 100, 'gamma': 0.001, 0.01, 0.1, 1, 10, 100} grid_search = GridSearchCV(SVC(), param_grid, cv=5, return_train_score=True)
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=0)
grid_search.fit(X_train, y_train)
print('Test set score: {:.2f}'.format(grid_search.score(X_test, y_test)))
--------------------------------------------------------------------------
Test set score: 0.97
--------------------------------------------------------------------------
// TODO P262